/*
 * Jabberd2-json-libs-java  
 * Copyright (C) 2010 Antti Leppä / Foyt
 * http://www.foyt.fi
 * 
 * License: 
 * 
 * Licensed under GNU General Public License Version 3 (GPL) 
 * http://www.gnu.org/licenses/gpl.html
 */

package fi.foyt.jabberd2json;

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.codec.binary.Base64;

/**
 * Abstract implementation of ObjectSetHandler. 
 * 
 * Provides few convenience methods data handling  
 */
public abstract class AbstractObjectSetHandler implements ObjectSetHandler {

  /**
   * Returns value as string according to name specified or null if non found
   * 
   * @param values Map of values
   * @param name value's name
   * @return value as string according to name specified or null if non found
   */
  protected String getStringValue(Map<String, String> values, String name) {
    return values.get(name);
  }
  
  /**
   * Returns value as NAD according to name specified or null if non found
   * 
   * @param values Map of values
   * @param name value's name
   * @return value as NAD according to name specified or null if non found
   */
  protected String getNadValue(Map<String, String> values, String name) {
    String value = getStringValue(values, name);
    if ((value != null) && (value.length() > 3))
      return value.substring(3);
    
    return null;
  }
  
  /**
   * Returns value as Integer according to name specified or null if non found
   * 
   * @param values Map of values
   * @param name value's name
   * @return value as Integer according to name specified or null if non found
   */
  protected Integer getIntegerValue(Map<String, String> values, String name) {
    String value = getStringValue(values, name);
    if ((value != null) && (!"".equals(value.trim()))) {
      Matcher matcher = Pattern.compile("^[0-9]*$").matcher(value);
      if (matcher.matches())
        return Integer.parseInt(value);
      else
        return null;
    }
    
    return null;
  }
  
  /**
   * Returns value as Boolean according to name specified or null if non found
   * 
   * @param values Map of values
   * @param name value's name
   * @return value as Boolean according to name specified or null if non found
   */
  protected Boolean getBooleanValue(Map<String, String> values, String name) {
    String value = getStringValue(values, name);
    if ((value != null) && (!"".equals(value.trim())))
      return "1".equals(value) ? Boolean.TRUE : Boolean.FALSE;
    
    return null;
  }
  
  /**
   * Returns value as Date according to name specified or null if non found
   * 
   * @param values Map of values
   * @param name value's name
   * @return value as Date according to name specified or null if non found
   */
  protected Date getDateValue(Map<String, String> values, String name) {
    Integer time = getIntegerValue(values, name);
    if (time != null && time > 0) {
      Date result = new Date(time * 1000);
      
      Calendar calendar = new GregorianCalendar();
      calendar.add(Calendar.YEAR, -1);
      
      Date yearAgo = calendar.getTime(); 
      
      if (yearAgo.before(result))
        return result;
      else
        return null;
    }
    
    return null;
  }

  /**
   * Creates ObjectSetField from String value. Returns null if value is null or blank 
   * 
   * @param type type of object 
   * @param key name of the value
   * @param value value
   * @return ObjectSetField or null if value is null or blank 
   */
  protected ObjectSetField createField(ObjectType type, String key, String value) {
    if ((value != null) && (!"".equals(value)))
      return new ObjectSetField(type, key, value);
    
    return null;
  }
  
  /**
   * Creates ObjectSetField from Long value. Returns null if value is null
   * 
   * @param key name of the value
   * @param value value
   * @return ObjectSetField or null if value is null
   */
  protected ObjectSetField createField(String key, Long value) {
    return createField(ObjectType.INTEGER, key, String.valueOf(value));
  }
  
  /**
   * Creates ObjectSetField from Integer value. Returns null if value is null
   * 
   * @param key name of the value
   * @param value value
   * @return ObjectSetField or null if value is null
   */
  protected ObjectSetField createField(String key, Integer value) {
    return createField(ObjectType.INTEGER, key, String.valueOf(value));
  }
  
  /**
   * Creates ObjectSetField from Date value. Returns null if value is null
   * 
   * @param key name of the value
   * @param value value
   * @return ObjectSetField or null if value is null
   */
  protected ObjectSetField createField(String key, Date value) {
    if (value != null)
      return createField(ObjectType.INTEGER, key, String.valueOf(Math.round(value.getTime() / 1000)));
    
    return null;
  }

  /**
   * Creates ObjectSetField from byte array. Returns null if array is empty or value is null 
   * 
   * @param key name of the value
   * @param value value
   * @return ObjectSetField or null if value is null
   */
  protected ObjectSetField createField(String key, byte[] value) {
    if ((value != null) && (value.length > 0))
      return createField(ObjectType.STRING, key, Base64.encodeBase64String(value));
    
    return null;
  }
  
  protected ObjectSetField createField(String key, boolean value) {
    return createField(ObjectType.BOOLEAN, key, value ? "1" : "0");
  }
  
}
